package cn.skyquant.quant4j.api.strategy;

import java.io.Serializable;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.HashMap;
import java.util.Map;

public class StrategyTestStatisticsMap implements Serializable {
    private static final long serialVersionUID = 1L;
    public final int id;
    public final String name;
    public double[] tp;
    public double[] sl;
    public double[] profit;
    public int[] num;
    public int[] tpnum;
    public int[] slnum;

    public long[] time;
    public long[] tptime;
    public long[] sltime;
    public long[] avgtime;
    public long[] avgtptime;
    public long[] avgsltime;

    public double[] amount;
    public double[] slamount;
    public double[] tpamount;
    public double[] avgamount;
    public double[] avgslamount;
    public double[] avgtpamount;

    public int[] dist;
    public int[] tpdist;
    public int[] sldist;
    public int[] avgdist;
    public int[] avgtpdist;
    public int[] avgsldist;
    private Map<Integer,StrategyTestStatisticsTotal> map = new HashMap<>();

    public void init(Map<Integer,Integer> indexMap){
        if(indexMap.isEmpty()){
            return;
        }
        int size = indexMap.size();
        tp = new double[size];
        sl = new double[size];
        profit = new double[size];
        num = new int[size];
        tpnum = new int[size];
        slnum = new int[size];

        time = new long[size];
        tptime = new long[size];
        sltime = new long[size];
        avgtime = new long[size];
        avgtptime = new long[size];
        avgsltime = new long[size];

        amount = new double[size];
        slamount = new double[size];
        tpamount = new double[size];
        avgamount = new double[size];
        avgslamount = new double[size];
        avgtpamount = new double[size];

        dist = new int[size];
        tpdist = new int[size];
        sldist = new int[size];
        avgdist = new int[size];
        avgtpdist = new int[size];
        avgsldist = new int[size];
        map.forEach((k,v)->{
            if(indexMap.containsKey(k)){
                int index= indexMap.get(k);

                tp[index] = new BigDecimal(v.tp).setScale(2, RoundingMode.HALF_UP).doubleValue();
                sl[index] = new BigDecimal(v.sl).setScale(2, RoundingMode.HALF_UP).doubleValue();
                profit[index] = new BigDecimal(v.profit).setScale(2, RoundingMode.HALF_UP).doubleValue();

                num[index] = v.num;
                tpnum[index] = v.tpnum;
                slnum[index] = v.slnum;

                time[index] = v.time;
                tptime[index] = v.tptime;
                sltime[index] = v.sltime;
                avgtime[index] = v.num==0?0:v.time/v.num;
                avgtptime[index] = v.tpnum==0?0:v.tptime/v.tpnum;
                avgsltime[index] = v.slnum==0?0:v.sltime/v.slnum;

                amount[index] = new BigDecimal(v.amount).setScale(6, RoundingMode.HALF_UP).doubleValue();
                tpamount[index] = new BigDecimal(v.tpamount).setScale(6, RoundingMode.HALF_UP).doubleValue();
                slamount[index] = new BigDecimal(v.slamount).setScale(6, RoundingMode.HALF_UP).doubleValue();
                avgamount[index] = new BigDecimal(v.num==0?0:v.amount/v.num).setScale(6, RoundingMode.HALF_UP).doubleValue();
                avgtpamount[index] = new BigDecimal(v.tpnum==0?0:v.tpamount/v.tpnum).setScale(6, RoundingMode.HALF_UP).doubleValue();
                avgslamount[index] = new BigDecimal(v.slnum==0?0:v.slamount/v.slnum).setScale(6, RoundingMode.HALF_UP).doubleValue();

                dist[index] = v.dist;
                tpdist[index] = v.tpdist;
                sldist[index] = v.sldist;
                avgdist[index] = v.num==0?0:v.dist/v.num;
                avgtpdist[index] = v.tpnum==0?0:v.tpdist/v.tpnum;
                avgsldist[index] = v.slnum==0?0:v.sldist/v.slnum;

            }
        });

    }


    public StrategyTestStatisticsMap(int id, String name) {
        this.id = id;
        this.name = name;
    }

    public void put(int tradeLevel,double profit,long begin,long end,double amount,int dist){
        StrategyTestStatisticsTotal total = map.get(tradeLevel);
        if(total==null){
            total = new StrategyTestStatisticsTotal(tradeLevel);
            map.put(tradeLevel,total);
        }
        long timediff = (end-begin)/60000;
        total.profit += profit;
        total.num ++;
        total.time += timediff;
        total.amount += amount;
        total.dist += dist;
        if(profit>=0){
            total.tp += profit;
            total.tpnum ++;
            total.tptime += timediff;
            total.tpamount += amount;
            total.tpdist += dist;
        }else {
            total.sl += profit;
            total.slnum ++;
            total.sltime += timediff;
            total.slamount += amount;
            total.sldist += dist;
        }
    }
}
